<template>
  <div>
    <el-card class="box-card" style="margin-bottom: 10px;">
      <!-- 表单部分 -->
      <el-form :inline="true" :model="form" class="demo-ruleForm" :rules="rules" ref="form" label-width="auto"
        style="height: 50px;">
        <el-form-item label="不等式组" prop="name" label-width="80px">
          <el-select v-model="form.name" placeholder="请选择不等式" style="width: 150px;">
            <el-option v-for="ineq in ineqName" :key="ineq" :label="ineq" :value="ineq" />
          </el-select>
        </el-form-item>
        <el-form-item label="不等式处理方法" prop="bilateral">
          <el-tooltip effect="dark" content="将每个双边不等式视作单边/双边不等式处理" placement="top">
            <el-select v-model="form.bilateral" placeholder="请选择不等式类型" style="width: 160px;">
              <el-option label="单边不等式" value=false></el-option>
              <el-option label="双边不等式" value=true></el-option>
            </el-select>
          </el-tooltip>
        </el-form-item>
        <el-form-item label="最大迭代次数" prop="maxCount" label-width="110px">
          <el-tooltip effect="dark" content="不宜过小或过大，建议选择30步" placement="top">
            <el-input v-model.number="form.maxCount" placeholder="请输入最大迭代次数" style="width: 160px;"></el-input>
          </el-tooltip>
        </el-form-item>
        <el-form-item label="不等式数量" prop="numInequ" label-width="100px">
          <el-tooltip effect="dark" placement="top">
            <div slot="content">求解使用的不等式数量<br />{{ numberContent }}</div>
            <el-input v-model.number="form.numInequ" placeholder="请输入不等式数量" style="width: 150px;"></el-input>
          </el-tooltip>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" :loading="submitLoading" @click="submitForm('form')">提交</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <el-dialog :title="dialogTitle" :visible="dialogVisible" width="30%" center :before-close="handleClose">
      <span v-if="progress < 100">求解时间较长，请耐心等待</span>
      <el-progress :percentage="progress" />
      <span slot="footer" class="dialog-footer">
        <el-button type="danger" :disabled="progress >= 100" @click="handleClose">取消生成</el-button>
        <el-button type="primary" :loading="okLoading" @click="dialogVisible = false">确 定</el-button>
      </span>
    </el-dialog>

    <el-empty v-if="!haveSolvedInequ" description="暂无求解结果，请先求解！"></el-empty>

    <el-card v-else class="box-card">
      <div slot="header" class="clearfix header-container">
        <span style="font-size: 18px;font-weight: bold;">{{ headerTiltle }}</span>
        <div class="right-aligned-items">
          <span>请选择要查看的迭代步骤:</span>
          <el-select v-model="selectedStep" placeholder="请选择查看的步骤数据" style="width: 200px; margin: 0 10px;">
            <el-option v-for="step in stepList" :key="step" :label="step" :value="step" />
          </el-select>
        </div>
      </div>
      <el-row>
        <el-col :span="6" v-for="(data, index) in probabilityDataSets" :key="index">
          <bar-chart :chartData="data" :title="currentChartTitles[index]" :truth="truthKeys[index]" height="120px">
          </bar-chart>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="18">
          <el-pagination @current-change="handleCurrentChange" :current-page="currentPage" :page-size="pageSize"
            layout="prev, pager, next, jumper" :total="totalDistTableData" style="margin-top: 5px;" small />
        </el-col>
        <el-col :span="4" class="legend-container">
          <div class="legend-item" style="background-color: #F4CE14;"></div>
          <span style="font-size: 14px;">已恢复</span>
          <div class="legend-item" style="background-color: #EED3D9;"></div>
          <span style="font-size: 14px;">未恢复</span>
        </el-col>
        <el-col :span="2">
          <el-button type="primary" plain style="margin-top: 5px;" @click="open2">结果说明</el-button>
        </el-col>
      </el-row>

    </el-card>
  </div>
</template>

<script>
  import axios from 'axios';
  import BarChart from '../components/BarChart.vue';
  export default {
    name: 'SolveInequ',
    components: {
      BarChart
    },
    data() {
      var validateNumber = (rule, value, callback) => {
        if (!/^\d+$/.test(value)) {
          callback(new Error('请输入正整数'));
        } else if (parseInt(value, 10) % 2 !== 0) { // 进一步判断是否为偶数
          callback(new Error('请输入偶数'));
        } else {
          callback();
        }
      };
      var validateMaxCount = (rule, value, callback) => {
        if (!/^\d+$/.test(value)) {
          callback(new Error('请输入正整数'));
        } else {
          callback();
        }
      };
      return {
        form: {
          name: '',
          bilateral: '',
          numInequ: '',
          maxCount: ''
        },
        rules: {
          name: [
            { required: true, message: '请选择不等式组', trigger: 'change' },
          ],
          bilateral: [
            { required: true, message: '请选择不等式类型', trigger: 'change' }
          ],
          numInequ: [
            { required: true, message: '请输入不等式数量', trigger: 'blur' },
            { validator: validateNumber, trigger: 'blur' }
          ],
          maxCount: [
            { required: true, message: '请输入最大迭代次数', trigger: 'blur' },
            { validator: validateMaxCount, trigger: 'blur' }
          ]
        },
        probabilityDataSets: [],
        chartTitles: [],
        currentChartTitles: [],
        ineqName: [],
        submitLoading: false, // 控制提交按钮的加载状态
        dialogVisible: false,
        dialogTitle: '求解不等式中',
        progress: 0,
        okLoading: true,
        stepList: [],
        selectedStep: 0,
        totalDistTableData: 1536,
        currentPage: 1,
        pageSize: 12,
        truthKeys: [],
        haveSolvedInequ: false,
        headerTiltle: '不等式求解成功，已恢复全部密钥分量！',
        version: '',
        numberContent: '暂未选择不等式组'
      };
    },
    mounted() {
      this.ineqName = sessionStorage.getItem('ineqName') ? JSON.parse(sessionStorage.getItem('ineqName')) : [];
      // this.ineqName = ['cutfilter_Kyber768Simplified_seed7175']
    },
    watch: {
      selectedStep: {
        handler(newVal, oldVal) {
          if (newVal) {
            this.updateChartTitles();
            this.fetchStepData();
          }
        },
        immediate: true // 确保初始时也执行
      },
      'form.name'(newValue, oldValue) {
        // console.log('不等式名称从', oldValue, '变为了', newValue);
        if (newValue) {
          // 执行你希望的操作
          const match = newValue.match(/\d+/);
          this.version = parseInt(match[0]);
          if (newValue[0] === 'c') {
            if (this.version == 512) {
              this.numberContent = '根据选择的不等式，5000个不等式可恢复全部密钥'
            } else if (this.version == 768) {
              this.numberContent = '根据选择的不等式，6500个不等式可恢复全部密钥'
            } else if (this.version == 1024) {
              this.numberContent = '根据选择的不等式，6500个不等式可恢复全部密钥'
            }
          } else if (newValue[0] === 'u') {
            if (this.version == 512) {
              this.numberContent = '根据选择的不等式，7500个不等式可恢复全部密钥'
            } else if (this.version == 768) {
              this.numberContent = '根据选择的不等式，12000个不等式可恢复全部密钥'
            } else if (this.version == 1024) {
              this.numberContent = '根据选择的不等式，7000个不等式可恢复全部密钥'
            }
          }
        }
      }
    },
    methods: {
      submitForm(formName) {
        this.haveSolvedInequ = false;
        this.okLoading = true;
        this.progress = 0; // 重置进度条
        this.dialogTitle = '不等式求解中';
        this.chartTitles = []
        this.stepList = []
        // console.log(this.form)
        this.$refs[formName].validate((valid) => {
          if (valid) {
            axios.post('http://127.0.0.1:8000/2/solveInequ', this.form, {
              headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
              }
            }).then(response => {
              // 请求成功，处理响应数据
              // 根据需要处理response.data，比如更新状态、显示消息等
              this.submitLoading = true;
              // 显示对话框
              this.dialogVisible = true;
              const progressCount = this.form.maxCount;

              // 使用 EventSource 更新进度条
              const eventSource = new EventSource('http://127.0.0.1:8000/2/solveInequ_SSE');
              eventSource.onmessage = (event) => {
                // console.log(event)
                // console.log(event.data)
                const data = event.data.split(' ');
                // console.log('Received data:', data);
                if (data[2] === 'str') {
                  eventSource.close();
                  this.progress = 100
                  console.log(data)
                  if (data[0] === 'True') {
                    this.dialogTitle = '成功恢复密钥';
                    this.headerTiltle = '不等式求解成功，已恢复全部密钥分量！'
                  } else if (data[0] === 'False') {
                    this.dialogTitle = '未能恢复密钥，请增加不等式数量'
                    this.headerTiltle = '密钥恢复失败，共恢复' + data[1] + '个分量！'
                  }
                  this.haveSolvedInequ = true
                  this.submitLoading = false;
                  this.okLoading = false;
                  const match = this.form.name.match(/\d+/);
                  this.version = parseInt(match[0]);
                  this.totalDistTableData = this.version + 256;
                  for (let i = 0; i < 256; i++) {
                    this.chartTitles.push(`e[${i}]`)
                  }
                  for (let i = 0; i < this.version; i++) {
                    this.chartTitles.push(`s[${i}]`)
                  }
                  this.selectedStep = this.stepList.at(-1)
                  this.resetForm('form');

                } else if (data[2] == 'int') {

                  // console.log('flor:',Math.floor(100 * Number(data[0]) / progressCount))
                  this.progress = Math.floor(100 * Number(data[0]) / progressCount)
                  this.stepList = Array.from({ length: Number(data[0]) + 1 }, (_, index) => index + 1);

                  // console.log('List:',this.stepList)
                  // console.log('[-1]:',this.stepList.at(-1))
                }
              };

              eventSource.onerror = (error) => {
                console.error('EventSource failed:', error);
                this.submitLoading = false;
                this.dialogTitle = '生成过程中出现错误';
                eventSource.close();
                this.okLoading = false;
              };
            }).catch(error => {
              // 请求失败，处理错误
              console.error('请求失败:', error);
              // 可以根据错误类型提示用户或采取其他措施
            });
          }
        })
      },
      handleClose(action) {
        if (this.progress >= 100 || action === 'confirm') {
          // this.fetchData();
          this.resetForm('form');
          this.updateChartTitles();
          this.fetchStepData();
          this.dialogVisible = false;
          eventSource.close();
          this.submitLoading = false;
        } else {
          this.$confirm('此操作将停止不等式求解, 是否继续?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            // 处理确认停止后的逻辑
            if (this.progress < 100) {

              this.$message({
                type: 'success',
                message: '成功取消!'
              });

              this.dialogVisible = false;
              this.submitLoading = false;
              this.shutSolveInequ();
              eventSource.close(); // 关闭 EventSource
              // 重置状态



            } else {
              this.$message({
                type: 'error',
                message: '已完成求解!'
              });
            }
          }).catch(() => {

          });
        }
      },
      shutSolveInequ() {
        // 使用 Axios 发起 POST 请求
        axios.get('http://127.0.0.1:8000/2/exterminate')
          .then(response => {
            // 请求成功，处理响应数据
            console.log('请求成功1:', response.data);
            // 根据需要处理response.data，比如更新状态、显示消息等
          })
          .catch(error => {
            // 请求失败，处理错误
            console.error('请求失败1:', error);
            // 可以根据错误类型提示用户或采取其他措施
          });
      },
      resetForm(formName) {
        this.$refs[formName].resetFields();
      },
      fetchStepData() {
        const startIndex = (this.currentPage - 1) * this.pageSize
        const endIndex = (this.currentPage) * this.pageSize

        axios.post('http://127.0.0.1:8000/2/getDist', {
          steps: this.selectedStep * 2,
          startIndex: startIndex,
          endIndex: endIndex

        }, {
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
          }
        }).then(response => {
          // console.log(response)
          this.probabilityDataSets = response.data['dist'];
          this.truthKeys = response.data['key']

        }).catch(error => {
          // 请求失败，处理错误
          console.error('请求失败:', error);
          // 可以根据错误类型提示用户或采取其他措施
        });
      },
      handleCurrentChange(page) {
        this.currentPage = page;

        this.$nextTick(() => {
          this.updateChartTitles();
          this.fetchStepData();
        });
      },
      updateChartTitles() {
        this.currentChartTitles = [];
        const version = this.version;
        this.currentChartTitles = this.chartTitles.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize)
      },
      open2() {
        const h = this.$createElement;

        this.$notify({
          title: '结果说明',
          message: h('i', { style: 'color: teal' }, '柱状图展示每个迭代步骤每个变量的概率分布向量，其中高亮为密钥真值。当高亮为粉色时，代表其未恢复；当其高亮为黄色时代表该系数已恢复。当恢复密钥一半分量时就可以利用公私钥关系式求解剩余密钥了。'),
          duration: 0,
        });
      }
    },
  };
</script>


<style scoped>

  .clearfix:before,
  .clearfix:after {
    display: table;
    content: "";
  }

  .clearfix:after {
    clear: both
  }

  .header-container {
    height: 25px;
    display: flex;
    /* 启用Flexbox布局 */
    align-items: center;
    /* 垂直居中对齐 */
  }

  .right-aligned-items {
    /* 新增一个类用于控制右侧元素的布局 */
    display: flex;
    align-items: center;
    margin-left: auto;
    /* 这将把这一组元素推到最右边 */
  }

  .legend-container {
    height: 50px;
    display: flex;
    /* 启用Flexbox布局 */
    align-items: center;
    /* 垂直居中对齐 */
  }

  .legend-item {
    width: 20px;
    height: 20px;
    margin: 10px;
    /* 可以添加边框、圆角等样式 */
  }
</style>
